package com.study.proxy;

import com.study.service.Calculator;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-08-22 21:15
 **/


/**
 * 必须要有接口，如果没有接口，不能使用，这种方式是使用JDK提供的 reflect 包下的类
 * 但是在生产环境中我不能保证每个类都有是实现的接口，所以有第二种方式 cglib
 * cglib 在实现的时候有没有接口都无所谓
 * <p>
 * <p>
 * 在 spring 中使用了两种动态代理的方式，一种是JDk提供的
 * 另外一种就是 cglib
 */
public class CalculatorProxy {

    public static Calculator getCalculator(final Calculator calculator) {
//        获取被代理对象的类加载器
        ClassLoader loader = calculator.getClass().getClassLoader();
//        被代理对象的所有接口
        Class<?>[] interfaces = calculator.getClass().getInterfaces();
//      用来执行被代理类需要执行的方法
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    System.err.println(method + "开始执行，参数是 " + Arrays.asList(args));
                    Object invoke = method.invoke(calculator, args);
                    System.err.println(method + "执行完成，结果是" + invoke);
                    return invoke;
//                开始调用被代理类的方法
                } catch (Exception e) {
                    e.printStackTrace();
                    System.err.println(method.getName() + "抛出异常" + e.getMessage());
                } finally {
                    System.err.println(method.getName() + "执行完成");
                }
                return null;
            }
        };
        Object o = Proxy.newProxyInstance(loader, interfaces, handler);
        return (Calculator) o;
    }
}
